package com.agilestudio.ifinance.service.account;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import com.agilestudio.ifinance.dao.account.MenuDao;
import com.agilestudio.ifinance.dao.account.RoleDao;
import com.agilestudio.ifinance.dao.account.UserDao;
import com.agilestudio.ifinance.entity.account.Menu;
import com.agilestudio.ifinance.entity.account.Role;
import com.agilestudio.ifinance.entity.account.User;
import com.agilestudio.modules.orm.Page;
import com.agilestudio.modules.orm.PropertyFilter;

/**
 * 安全相关实体的管理类, 包括用户,角色,资源与授权类.
 * 
 * @author Ethan
 */
// Spring Bean的标识.
@Component
// 默认将类中的所有函数纳入事务管理.
@Transactional
public class AccountService {

	protected Logger logger = LoggerFactory.getLogger(getClass());

	private UserDao userDao;
	private RoleDao roleDao;
	private MenuDao menuDao;

	// -- User Manager --//
	@Transactional(readOnly = true)
	public User getUser(Long id) {
		return userDao.get(id);
	}

	public void saveUser(User entity) {
		userDao.save(entity);
	}

	/**
	 * 判断是否超级管理员.
	 */
	private boolean isSupervisor(Long id) {
		return id == 1;
	}

	/**
	 * 使用属性过滤条件查询用户.
	 */
	@Transactional(readOnly = true)
	public Page<User> searchUser(final Page<User> page,
			final List<PropertyFilter> filters) {
		return userDao.findPage(page, filters);
	}

	@Transactional(readOnly = true)
	public User findUserByLoginName(String loginName) {
		return userDao.findUniqueBy("loginName", loginName);
	}

	/**
	 * 检查用户名是否唯一.
	 * 
	 * @return loginName在数据库中唯一或等于oldLoginName时返回true.
	 */
	@Transactional(readOnly = true)
	public boolean isLoginNameUnique(String newLoginName, String oldLoginName) {
		return userDao
				.isPropertyUnique("loginName", newLoginName, oldLoginName);
	}
	
	
	//Menu
	@Transactional(readOnly = true)
	public Menu getMenu(Long id) {
		return menuDao.get(id);
	}

	public void saveMenu(Menu entity) {
		menuDao.save(entity);
	}	
	
	@Transactional(readOnly = true)
	public Page<Menu> searchMenu(final Page<Menu> page,
			final List<PropertyFilter> filters) {
		return menuDao.findPage(page, filters);
	}	
	
	@Transactional(readOnly = true)
	public List<Menu> searchMenu(final List<PropertyFilter> filters) {
		return menuDao.find(filters);
	}		

	// -- Role Manager --//
	@Transactional(readOnly = true)
	public Role getRole(Long id) {
		return roleDao.get(id);
	}

	@Transactional(readOnly = true)
	public List<Role> getRoles() {
		return roleDao.getAll("id", true);
	}
	
	@Transactional(readOnly = true)
	public List<Menu> getOrganizedMenus() {
		List<Menu>  menus= this.getMenus();
		List<Menu>  organizedMenus= new ArrayList<Menu>();
		for (Iterator<Menu> iterator = menus.iterator(); iterator.hasNext();) {
			Menu menu = (Menu) iterator.next();
			if(menu.getCode().endsWith("000000")){
				List<Menu> children = new ArrayList<Menu>();
				menu.setMenus(children);
				for (Iterator<Menu> iterator2 = menus.iterator(); iterator2
						.hasNext();) {
					Menu menu2 = (Menu) iterator2.next();
					if(!menu2.getCode().equals(menu.getCode()) && menu2.getCode().startsWith(menu.getCode().substring(0, 2))){
						children.add(menu2);
					}
				}
				organizedMenus.add(menu);
			}
		}
		return organizedMenus;
	}	

	@Transactional(readOnly = true)
	public List<Menu> getMenus() {
		return menuDao.getAll();
	}

	@Transactional(readOnly = true)
	public List<Menu> getMenus(String code, List<Menu> omenus) {
		List<Menu> menus = new ArrayList<Menu>();
		for(Menu menu:omenus){
			String mc = menu.getCode();
			if ("".equals(code)) {
				if(mc.endsWith("000000")){
					menus.add(menu);
				}
			}else if (code.charAt(2) == '0' && code.charAt(3) == '0' ){
				if(mc.startsWith(code.substring(0,2)) && !"00".equals(mc.substring(2, 4)) && mc.endsWith("0000")){
					menus.add(menu);
				}
			}else if (code.charAt(4) == '0' && code.charAt(5) == '0'){
				if(mc.startsWith(code.substring(0,4)) && !"00".equals(mc.substring(4, 6)) && mc.endsWith("00")){
					menus.add(menu);
				}
			}else if (code.charAt(6) == '0' && code.charAt(7) == '0'){
				if(mc.startsWith(code.substring(0,6)) && !"00".equals(mc.substring(6, 8))){
					menus.add(menu);
				}
			}			
		}
		return menus;
	}
	
	@Transactional(readOnly = true)
	public Page<Role> searchRole(final Page<Role> page,
			final List<PropertyFilter> filters) {
		return roleDao.findPage(page, filters);
	}	
	
	@Transactional(readOnly = true)
	public List<Role> searchRole(final List<PropertyFilter> filters) {
		return roleDao.find(filters);
	}	
	
	@Transactional(readOnly = true)
	public List<User> getUsers() {
		return userDao.getAll();
	}	

	public void saveRole(Role entity) {
		roleDao.save(entity);
	}

	public void deleteRole(Long id) {
		roleDao.delete(id);
	}

	// -- Authority Manager --//
	@Transactional(readOnly = true)
	public List<Menu> getAllAuthority() {
		return menuDao.getAll();
	}

	@Autowired
	public void setUserDao(UserDao userDao) {
		this.userDao = userDao;
	}

	@Autowired
	public void setRoleDao(RoleDao roleDao) {
		this.roleDao = roleDao;
	}

	@Autowired
	public void setMenuDao(MenuDao menuDao) {
		this.menuDao = menuDao;
	}
}
